package com.swak.consistency.core.aspect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.springframework.core.annotation.AnnotatedElementUtils;

import com.swak.annotation.Consistency;
import com.swak.annotation.ConsistencyScheme;
import com.swak.annotation.Propagation;
import com.swak.consistency.ConsistencyLauncher;
import com.swak.consistency.core.attribute.ConsistencyAttribute;
import com.swak.utils.StringUtils;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * 一致性处理器
 * 
 * @author lifeng
 * @date 2021年1月28日 下午12:54:35
 */
@Getter
@Setter
@Accessors(chain = true)
public class ConsistencyProceeding implements ConsistencyAttribute {

	/**
	 * 申明的类
	 */
	Class<?> declareClass;
	Field declareField;

	/**
	 * 真正执行的类
	 */
	Class<?> target;
	Method method;
	Object[] args;
	Proceeding proceeding;

	/**
	 * 事务方案
	 */
	ConsistencyScheme scheme;

	/**
	 * 传播级别
	 */
	Propagation propagation;

	/**
	 * 初始化
	 */
	void init() {
		if (scheme == null) {
			Consistency consistency = AnnotatedElementUtils.findMergedAnnotation(method, Consistency.class);
			this.scheme = consistency.scheme();
			this.propagation = consistency.propagation();
		}
	}

	/**
	 * 执行
	 * 
	 * @return
	 * @throws Throwable
	 */
	public Object proceed() throws Throwable {
		return proceeding.proceed();
	}

	/**
	 * 获得一致性方案的传播级别
	 * 
	 * @param point
	 * @return
	 */
	public Propagation getPropagation() {
		this.init();
		if (this.propagation == null) {
			return Propagation.REQUIRED;
		}
		return this.propagation;
	}

	/**
	 * 获得一致性方案
	 * 
	 * @param point
	 * @return
	 */
	public ConsistencyScheme getScheme() {
		this.init();
		if (this.scheme == null) {
			return ConsistencyScheme.TCC;
		}
		return this.scheme;
	}

	/**
	 * 准备阶段
	 * 
	 * @return
	 * @throws Throwable
	 */
	public Object prepare() throws Throwable {
		return ConsistencyLauncher.prepare(this);
	}

	/**
	 * 准备阶段、完成阶段： 远程数据发送
	 * 
	 * @return
	 * @throws Throwable
	 */
	public Object transmit() throws Throwable {
		return ConsistencyLauncher.transmit(this);
	}

	/**
	 * 完成阶段
	 * 
	 * @return
	 * @throws Throwable
	 */
	public Object complete() throws Throwable {
		return ConsistencyLauncher.complete(this);
	}

	/**
	 * 格式化输出
	 */
	@Override
	public String toString() {
		return StringUtils.format("类[%s], 方法[%s].", this.target.getSimpleName(), this.method.getName());
	}

	/**
	 * 创建
	 * 
	 * @param method
	 * @return
	 */
	public static ConsistencyProceeding of() {
		return new ConsistencyProceeding();
	}
}